package com.team2.cyber_eye.ActivityHelpers;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.team2.cyber_eye.CyberActivity;

import android.graphics.Bitmap;
import android.os.Environment;

public class IQE
{
	//Keys created on jan 20 2013
	protected static final String QUERY_API = "http://api.iqengines.com/v1.2/query/";
	protected static final String RESULT_API = "http://api.iqengines.com/v1.2/result/";
	protected static final String QUERY_API_KEY = "b9c792c8321848c2b3c899ed2a3b9558";
	protected static final String QUERY_API_SECRET = "57d4eb9aa3354bd5925cc2e9dda29e76";
	
	protected static File CleanBitmap(Bitmap sourceBitmap, String Name)
	{
		sourceBitmap = Util.LimitBitmap(sourceBitmap, 640);
		File file = null;
		try
		{
			file = new File(Environment.getExternalStorageDirectory() + "/" + Name);
			if (!file.exists()) file.createNewFile();
			file.deleteOnExit();
			FileOutputStream fos = new FileOutputStream(file);
			sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
			
			return file;
		}
		catch(Exception Ex)
		{
			Ex.toString();
			return null;
		}
	}
	
	public static String[] QueryIQEngine(Bitmap pictureBitmap)
	{
		String QueryID = null;
		String[] Result = {"QueryID", "Failed", "Unable to connect to the internet"};
		
	    try 
	    {
		    HttpClient httpClient = new DefaultHttpClient();
		    HttpPost pagePost = new HttpPost(QUERY_API);
		    String Hashable = "";
	        MultipartEntity entity = new MultipartEntity();
	        
	        //  Add parameters  ------------------------------------------------------  
	        Result[2] = "Unable to build IQE Query";

	        entity.addPart("api_key", new StringBody(QUERY_API_KEY));
	        Hashable += "api_key" + QUERY_API_KEY;

	        String imageName = "Image" + (pictureBitmap.hashCode() % 512) + ".jpg";
	        File bitmapFile = CleanBitmap(pictureBitmap, imageName);
	        Util.setIqeBitmapFile(bitmapFile);
	        entity.addPart("img", new FileBody(bitmapFile));
	        Hashable += "img" + imageName;

		    String timeStamp = Util.getDateString();
	        entity.addPart("time_stamp", new StringBody(timeStamp));
	        Hashable += "time_stamp" + timeStamp;
	        
	        //  Create signature  ------------------------------------------------------
		    String Secret = QUERY_API_SECRET;
		    SecretKeySpec signingKey = new SecretKeySpec(Secret.getBytes(), "HMAC-SHA1");
		    javax.crypto.Mac HashFunc = Mac.getInstance("HMAC-SHA1");

		    HashFunc.init(signingKey);
		    byte[] HashBytes = HashFunc.doFinal(Hashable.getBytes());
		    String HashCode = Util.HexConvert(HashBytes);

		    QueryID = HashCode;
		    
            entity.addPart("api_sig", new StringBody(HashCode));
            
            pagePost.setEntity(entity);
            
            //  Send message  ------------------------------------------------------
	        Result[2] = "Error Connecting to IQ Engine";
            
            HttpResponse response = httpClient.execute(pagePost);//fails here!!!!!!!
            HttpEntity resEntity = response.getEntity();
            
		    //  Manage response  ------------------------------------------------------
	        Result[2] = "Error Parsing IQ Engine results";
	        
		    InputStream resultSream = resEntity.getContent();
		    String strResult = Util.ReadFullStream(resultSream);
		    
		    Document xmlDoc = Util.ParseXMLString(strResult);
		    
		    Element parent = (Element)xmlDoc.getElementsByTagName("data").item(0);
		    Element error = (Element)parent.getElementsByTagName("error").item(0);
		    String errorValue = error.getFirstChild().getNodeValue();
		    
		    if (!errorValue.equalsIgnoreCase("0"))
		    {
			    Element comment = (Element)xmlDoc.getElementsByTagName("comment").item(0);
				Result[0] = null;
				Result[1] = "Failed";
				Result[2] = "IQ Engine reported error: " + comment.getFirstChild().getNodeValue();
				
			    return Result;
		    }
		    
			Result[0] = QueryID;
			Result[1] = "Passed";
			Result[2] = strResult;
	    }
	    catch (Exception ex)
	    {
			Result[0] = null;
			Result[1] = "Failed";
			Result[2] += "\n" + ex.toString();
	    }
	    
	    return Result;
	}

	public static String[] ResultIQEngine(String QueryID)
	{
		String[] Result = {"Name", "Failed", "No QueryID"};

    	if (QueryID == null) return Result;
    	
	    try
	    {
			for(int itr = 0; itr < 40; itr++)//this stage can take up to four minute
			{
				Result[2] = "Unable to re-connect to the internet";
				
			    HttpClient httpClient = new DefaultHttpClient();
			    HttpPost pagePost = new HttpPost(RESULT_API);
			    String Hashable = "";
		        MultipartEntity entity = new MultipartEntity();
		        
		        //  Add parameters  ------------------------------------------------------
				Result[2] = "Unable to build IQE Result Request";
				
		        entity.addPart("api_key", new StringBody(QUERY_API_KEY));
		        Hashable += "api_key" + QUERY_API_KEY;

		        entity.addPart("qid", new StringBody(QueryID));
		        Hashable += "qid" + QueryID;
		        
			    String timeStamp = Util.getDateString();
		        entity.addPart("time_stamp", new StringBody(timeStamp));
		        Hashable += "time_stamp" + timeStamp;

	            entity.addPart("qid", new StringBody(QueryID));

		        //  Create signature  ------------------------------------------------------
			    String Secret = QUERY_API_SECRET;
			    SecretKeySpec signingKey = new SecretKeySpec(Secret.getBytes(), "HMAC-SHA1");
			    javax.crypto.Mac HashFunc = Mac.getInstance("HMAC-SHA1");
			    
			    HashFunc.init(signingKey);
			    byte[] HashBytes = HashFunc.doFinal(Hashable.getBytes());
			    String HashCode = Util.HexConvert(HashBytes);

	            entity.addPart("api_sig", new StringBody(HashCode));
	            
	            //  Send message  ------------------------------------------------------
		        Result[2] = "Error re-connecting to IQ Engine";
		        
	            pagePost.setEntity(entity);
	            
	            HttpResponse response = httpClient.execute(pagePost);
	            HttpEntity resEntity = response.getEntity();
			    
			    //  Manage response  ------------------------------------------------------
		        Result[2] = "Error Parsing IQ Engine results";
			    InputStream resultSream = resEntity.getContent();
			    String xmlResult = Util.ReadFullStream(resultSream);

			    Document xmlDoc = Util.ParseXMLString(xmlResult);
			    
			    Element parent = (Element)xmlDoc.getElementsByTagName("data").item(0);
			    Element error = (Element)parent.getElementsByTagName("error").item(0);
			    String errorValue = error.getFirstChild().getNodeValue();
			    
			    if (!errorValue.equalsIgnoreCase("0"))
			    {
				    Element comment = (Element)xmlDoc.getElementsByTagName("comment").item(0);
					Result[0] = null;
					Result[1] = "Failed";
					Result[2] = "IQ Engine reported error: " + comment.getFirstChild().getNodeValue();
					
				    return Result;
			    }

			    Element results = (Element)xmlDoc.getElementsByTagName("results").item(0);
			    if (results != null)
			    {
				    Element labels = (Element)xmlDoc.getElementsByTagName("labels").item(0);
			    	String labelsStr = labels.getFirstChild().getNodeValue();

					Result[0] = labelsStr;
					Result[1] = "Passed";
					Result[2] = xmlResult;
					
					return Result;
			    }
			    
			    Thread.sleep(6000);//6 seconds
			}
			
			Result[1] = "Failed";
		    Result[2] = "IQ Engine timed out searching for item after 4 minutes";
	    }
	    catch (Exception ex)
	    {
			Result[0] = null;
			Result[1] = "Failed";
			Result[2] += "\n" + ex.toString();
	    }
	    
	    return Result;
	}
}
